/**
 * @file mysql_pool.h
 * @brief MySQL连接池 - 基于MySQL C API的高性能数据库连接池
 * @author 29108
 * @date 2025/7/5
 * @version 1.0
 *
 * 功能特性:
 * - 线程安全的连接池管理
 * - 自动连接健康检查和重连
 * - 连接超时和空闲超时管理
 * - RAII风格的连接管理器
 * - 支持事务管理
 * - 详细的连接统计信息
 *
 * 使用示例:
 * @code
 * MySQLPool::Config config;
 * config.host = "localhost";
 * config.user = "root";
 * config.password = "password";
 * config.database = "test_db";
 *
 * MySQLPool pool(config);
 * pool.start();
 *
 * // 使用RAII管理器
 * {
 *     MySQLConnectionGuard guard(pool);
 *     auto result = guard->executeQuery("SELECT * FROM users");
 *     // 连接自动归还到池中
 * }
 * @endcode
 */

#ifndef MYSQL_POOL_H
#define MYSQL_POOL_H

// 标准库头文件
#include <string>
#include <memory>
#include <queue>
#include <set>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <atomic>
#include <chrono>
#include <map>
#include <future>
#include <vector>
#include <mysql_driver.h>
#include <mysql_connection.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include <cppconn/resultset.h>
#include <cppconn/exception.h>
#include <stdexcept>
#include "./common/config/config_manager.h"
#include "./common/thread_pool/thread_pool.h"

namespace common {
    namespace database {

        class MySQLConnection {
        public:
            // 连接配置结构体
            struct ConnectionConfig {
                bool auto_reconnect = true;
                std::string charset = "utf8mb4";
                unsigned int connect_timeout = 10;  // 秒
                unsigned int read_timeout = 30;     // 秒
                unsigned int write_timeout = 30;    // 秒
            };

            MySQLConnection(const std::string& host, int port,
                           const std::string& user, const std::string& password,
                           const std::string& database);

            MySQLConnection(const std::string& host, int port,
                           const std::string& user, const std::string& password,
                           const std::string& database, const ConnectionConfig& config);
            ~MySQLConnection();

            // 连接管理
            bool connect();
            void disconnect();
            bool isConnected() const;
            bool ping();
            bool isValid() const;

            // SQL执行
            std::unique_ptr<sql::ResultSet> executeQuery(const std::string& sql);
            int executeUpdate(const std::string& sql);
            std::unique_ptr<sql::PreparedStatement> prepareStatement(const std::string& sql);

            // 事务管理
            void beginTransaction();
            void commit();
            void rollback();
            void setAutoCommit(bool autoCommit);

            // 连接信息
            std::chrono::system_clock::time_point getLastUsed() const { return last_used_; }
            void updateLastUsed() { last_used_ = std::chrono::system_clock::now(); }
            const std::string& getConnectionId() const { return connection_id_; }

        private:
            std::unique_ptr<sql::Connection> connection_;
            sql::mysql::MySQL_Driver* driver_;
            std::string host_;
            int port_;
            std::string user_;
            std::string password_;
            std::string database_;
            std::string connection_string_;
            std::string connection_id_;
            std::chrono::system_clock::time_point last_used_;
            mutable std::mutex connection_mutex_;

            // 连接配置选项
            bool auto_reconnect_ = true;
            std::string charset_ = "utf8mb4";
            unsigned int connect_timeout_ = 10;  // 秒
            unsigned int read_timeout_ = 30;     // 秒
            unsigned int write_timeout_ = 30;    // 秒

            void generateConnectionId();
            std::string buildConnectionString();
            bool isConnectedNoLock() const;  // 内部使用的无锁版本
        };

        class MySQLPool {
        public:
            struct mysqlConfig {
                std::string host = "dev-mysql";
                int port = 3306;
                std::string user;
                std::string password;
                std::string database;
                size_t initial_size = 5;
                size_t max_size = 50;
                size_t min_size = 2;
                std::chrono::minutes idle_timeout{10};
                std::chrono::seconds health_check_interval{30};
                bool auto_reconnect = true;
                std::string charset = "utf8mb4";
                unsigned int connect_timeout = 30;
                unsigned int read_timeout = 30;
                unsigned int write_timeout = 30;

                // 线程池配置
                size_t thread_pool_core_size = 2;        ///< 线程池核心线程数
                size_t thread_pool_max_size = 8;         ///< 线程池最大线程数
                size_t thread_pool_queue_capacity = 100; ///< 任务队列容量
                int thread_pool_keep_alive_ms = 60000;   ///< 线程存活时间(毫秒)
                bool enable_async_operations = true;     ///< 是否启用异步操作

                // ==================== 新增ConfigManager集成方法 ====================
                /**
                 * @brief 从ConfigManager加载MySQL连接池配置
                 * @return 配置好的Config实例
                 * @details 从统一配置中读取database.mysql.*配置项
                 */
                static mysqlConfig fromConfigManager() {
                    auto& config = common::config::ConfigManager::getInstance();
                    mysqlConfig result;

                    // 基础连接配置
                    result.host = config.get<std::string>("database.mysql.host", "localhost");
                    result.port = config.get<int>("database.mysql.port", 3306);
                    result.user = config.get<std::string>("database.mysql.user");
                    result.password = config.get<std::string>("database.mysql.password");
                    result.database = config.get<std::string>("database.mysql.database");

                    // 连接池配置
                    result.initial_size = config.get<size_t>("database.mysql.pool.initial_size", 5);
                    result.max_size = config.get<size_t>("database.mysql.pool.max_size", 20);
                    result.min_size = config.get<size_t>("database.mysql.pool.min_size", 2);

                    // 超时配置 (配置文件中以秒为单位)
                    auto idle_timeout_seconds = config.get<int>("database.mysql.pool.idle_timeout", 600);
                    result.idle_timeout = std::chrono::minutes(idle_timeout_seconds / 60);

                    auto health_check_seconds = config.get<int>("database.mysql.pool.health_check_interval", 30);
                    result.health_check_interval = std::chrono::seconds(health_check_seconds);

                    // 连接属性配置
                    result.auto_reconnect = config.get<bool>("database.mysql.connection.auto_reconnect", true);
                    result.charset = config.get<std::string>("database.mysql.connection.charset", "utf8mb4");
                    result.connect_timeout = config.get<unsigned int>("database.mysql.connection.connect_timeout", 10);
                    result.read_timeout = config.get<unsigned int>("database.mysql.connection.read_timeout", 30);
                    result.write_timeout = config.get<unsigned int>("database.mysql.connection.write_timeout", 30);

                    // 线程池配置
                    result.thread_pool_core_size = config.get<size_t>("database.mysql.thread_pool.core_size", 2);
                    result.thread_pool_max_size = config.get<size_t>("database.mysql.thread_pool.max_size", 8);
                    result.thread_pool_queue_capacity = config.get<size_t>("database.mysql.thread_pool.queue_capacity", 100);
                    result.thread_pool_keep_alive_ms = config.get<int>("database.mysql.thread_pool.keep_alive_ms", 60000);
                    result.enable_async_operations = config.get<bool>("database.mysql.thread_pool.enable_async_operations", true);

                    return result;
                }

                /**
                 * @brief 验证配置参数的有效性
                 * @throws std::runtime_error 当配置无效时抛出异常
                 */
                void validate() const {
                    if (host.empty()) {
                        throw std::runtime_error("MySQL host cannot be empty");
                    }
                    if (port <= 0 || port > 65535) {
                        throw std::runtime_error("Invalid MySQL port: " + std::to_string(port));
                    }
                    if (user.empty()) {
                        throw std::runtime_error("MySQL user cannot be empty");
                    }
                    if (password.empty()) {
                        throw std::runtime_error("MySQL password cannot be empty");
                    }
                    if (database.empty()) {
                        throw std::runtime_error("MySQL database cannot be empty");
                    }
                    // 允许 initial_size = 0，表示启动时不预创建连接，按需创建
                    if (max_size == 0) {
                        throw std::runtime_error("MySQL pool max_size must be greater than 0");
                    }
                    if (max_size < initial_size) {
                        throw std::runtime_error("MySQL pool max_size must be >= initial_size");
                    }
                    if (min_size > initial_size) {
                        throw std::runtime_error("MySQL pool min_size must be <= initial_size");
                    }
                    if (thread_pool_core_size == 0) {
                        throw std::runtime_error("MySQL thread pool core_size must be greater than 0");
                    }
                    if (thread_pool_max_size < thread_pool_core_size) {
                        throw std::runtime_error("MySQL thread pool max_size must be >= core_size");
                    }
                    if (thread_pool_queue_capacity == 0) {
                        throw std::runtime_error("MySQL thread pool queue_capacity must be greater than 0");
                    }
                }

                /**
                 * @brief 支持配置热更新
                 * @details 从ConfigManager重新加载配置并验证
                 */
                void updateFromConfigManager() {
                    *this = fromConfigManager();
                    validate();
                }
            };

            explicit MySQLPool(const mysqlConfig& config);
            explicit MySQLPool();
            ~MySQLPool();

            // 连接管理
            std::shared_ptr<MySQLConnection> getConnection(std::chrono::milliseconds timeout = std::chrono::milliseconds(2000));
            void returnConnection(std::shared_ptr<MySQLConnection> conn);

            // 统计信息
            size_t getActiveConnections() const;
            size_t getIdleConnections() const;
            size_t getTotalConnections() const;

            // 控制方法
            void start();
            void stop();
            bool isRunning() const { return running_.load(); }

            /**
            * @brief 启用配置热更新监听
            * @details 监听ConfigManager中MySQL相关配置的变化
            */
            void enableConfigHotReload();

            // ==================== 线程池相关方法 ====================

            /**
             * @brief 初始化线程池
             * @details 根据配置创建和配置线程池
             */
            void initializeThreadPool();

            /**
             * @brief 关闭线程池
             * @details 优雅关闭所有线程池
             */
            void shutdownThreadPool();

            /**
             * @brief 异步创建连接
             * @param count 需要创建的连接数量
             * @return 返回future，可以等待创建完成
             */
            std::future<std::vector<std::shared_ptr<MySQLConnection>>> createConnectionsAsync(size_t count);

            /**
             * @brief 异步健康检查
             * @details 并行检查所有连接的健康状态
             */
            void performAsyncHealthCheck();

            /**
             * @brief 异步清理过期连接
             * @details 在后台线程中清理过期和无效连接
             */
            void cleanupExpiredConnectionsAsync();

            /**
             * @brief 获取线程池状态信息
             * @return 线程池状态字符串
             */
            std::string getThreadPoolStatus() const;

        private:
            mysqlConfig config_;
            std::queue<std::shared_ptr<MySQLConnection>> idle_connections_;
            std::set<std::shared_ptr<MySQLConnection>> active_connections_;
            mutable std::mutex pool_mutex_;
            std::condition_variable condition_;
            std::thread health_check_thread_;
            std::atomic<bool> running_;

            // 内部方法
            void healthCheck();
            std::shared_ptr<MySQLConnection> createConnection();
            void removeExpiredConnections();
            void ensureMinimumConnections();
            bool validateConnection(std::shared_ptr<MySQLConnection> conn);

            std::atomic<bool> restart_required_{false};                     ///< 是否需要重启连接池
            std::atomic<bool> accepting_new_connections_{true};             ///< 是否接受新连接

            // ==================== 线程池集成 ====================
            std::shared_ptr<common::thread_pool::ThreadPool> thread_pool_;  ///< 主线程池，用于各种异步操作
            std::shared_ptr<common::thread_pool::ThreadPool> restart_thread_pool_; ///< 专用于重启操作的线程池
            std::atomic<bool> thread_pool_initialized_{false};              ///< 线程池是否已初始化

            /**
 * @brief 标记Redis连接池需要重启
 * @details 某些关键配置变化需要重启整个连接池
 */
            void markForRestart();

            /**
 * @brief 调度重启检查任务
 * @details 异步执行重启检查，避免阻塞配置更新线程
 */
            void scheduleRestartCheck();

            /**
             * @brief 检查并处理重启需求
             * @details 实际执行重启逻辑的核心方法
             */
            void checkAndHandleRestart();

            /**
             * @brief 设置是否接受新连接
             * @param accepting 是否接受新连接
             */
            void setAcceptingNewConnections(bool accepting);

            /**
             * @brief 等待活跃连接完成当前操作
             * @details 优雅等待，避免强制中断正在进行的操作
             */
            void waitForActiveConnectionsToFinish();

            /**
             * @brief 关闭所有现有连接
             * @details 强制关闭所有连接，包括空闲和活跃的连接
             */
            void closeAllConnections();

            /**
             * @brief 重新加载配置
             * @details 从ConfigManager重新加载最新配置
             */
            void reloadConfiguration();

            /**
             * @brief 重新初始化连接池
             * @return 是否初始化成功
             */
            bool reinitializePool();

            /**
            * @brief 动态调整Redis连接池大小
            * @param new_max_size 新的最大连接数
            * @details 可以在运行时增加连接池大小，但不能减少（避免影响现有连接）
            */
            void adjustPoolSize(size_t new_max_size);

        };

        // RAII连接管理器
        class MySQLConnectionGuard {
        public:
            MySQLConnectionGuard(MySQLPool& pool, std::chrono::milliseconds timeout = std::chrono::milliseconds(15000))
                : pool_(pool), connection_(pool.getConnection(timeout)) {}

            ~MySQLConnectionGuard() {
                if (connection_) {
                    pool_.returnConnection(connection_);
                }
            }

            MySQLConnection* operator->() { return connection_.get(); }
            MySQLConnection& operator*() { return *connection_; }
            MySQLConnection* get() { return connection_.get(); }

            // 禁止拷贝
            MySQLConnectionGuard(const MySQLConnectionGuard&) = delete;
            MySQLConnectionGuard& operator=(const MySQLConnectionGuard&) = delete;

        private:
            MySQLPool& pool_;
            std::shared_ptr<MySQLConnection> connection_;
        };

    } // namespace database
} // namespace common

#endif // MYSQL_POOL_H
